﻿using Sidvall.Serialization;
using System.Collections.Generic;
using System.Linq;

namespace Sidvall.AuthorizationManager.Data
{
	public class ResourceItemCollection : System.Collections.ObjectModel.Collection<ResourceItem>
	{
		#region Public Members

		#region AddRange

		public void AddRange(IEnumerable<ResourceItem> items)
		{
			if (items == null)
				return;
			foreach (var item in items)
				Add(item);
		}

		#endregion
		#region GetDescription

		public string GetDescription(string resourceItemSeparator)
		{
			return GetDescription(resourceItemSeparator, false, false, " - ");
		}
		public string GetDescription(string resourceItemSeparator, bool includeAction, bool includeSubAction, string claimSeparator)
		{
			var sb = new System.Text.StringBuilder();
			var orderedItems = (from o in this
								orderby o.Priority
								select o);
			foreach (var item in orderedItems)
			{
				var d = item.GetDescription(includeAction, includeSubAction, claimSeparator);
				if (sb.Length > 0)
					sb.Append(resourceItemSeparator);
				sb.Append(d);
			}
			return sb.ToString();
		}

		#endregion
		#region GetResourceAccessLevel

		public ResourceAccessLevel GetResourceAccessLevel()
		{
			var result = ResourceAccessLevel.None;
			foreach (var item in this)
			{
				switch (item.AccessLevel)
				{
					case ResourceAccessLevel.Public:
						return ResourceAccessLevel.Public;
					case ResourceAccessLevel.Authenticated:
						switch (result)
						{
							case ResourceAccessLevel.AuthenticatedAndClaims:
							case ResourceAccessLevel.None:
								result = item.AccessLevel;
								break;
							default:
								break;
						}
						break;
					case ResourceAccessLevel.AuthenticatedAndClaims:
						switch (result)
						{
							case ResourceAccessLevel.None:
								result = item.AccessLevel;
								break;
							default:
								break;
						}
						break;
					case ResourceAccessLevel.Claims:
						switch (result)
						{
							case ResourceAccessLevel.Authenticated:
							case ResourceAccessLevel.AuthenticatedAndClaims:
							case ResourceAccessLevel.None:
								result = item.AccessLevel;
								break;
							default:
								break;
						}
						break;
					default:
						break;
				}
			}
			return result;
		}

		#endregion
		#region Load

		public void Load(ResourceAccessLevel accessLevel, IEnumerable<IClaimItem> claims, bool hasResource, bool validForResourceActionItems, string actions, string subActions)
		{
			ResourceItem resourceItem;
			string[] actionItems, subActionItems;

			if ((!hasResource) || (string.IsNullOrWhiteSpace(actions)))
			{
				resourceItem = new ResourceItem(accessLevel, claims, validForResourceActionItems);
				Add(resourceItem);
			}
			else
			{
				actionItems = actions.Split(AuthorizationScopeItemManager.ActionSeparator);
				foreach (var actionItem in actionItems)
				{
					if (string.IsNullOrWhiteSpace(actionItem))
					{
						resourceItem = new ResourceItem(accessLevel, claims, validForResourceActionItems);
						Add(resourceItem);
					}
					else if (string.IsNullOrWhiteSpace(subActions))
					{
						resourceItem = new ResourceItem(accessLevel, claims, validForResourceActionItems, actionItem, null);
						Add(resourceItem);
					}
					else
					{
						subActionItems = subActions.Split(AuthorizationScopeItemManager.SubActionSeparator);
						foreach (var subActionItem in subActionItems)
						{
							if (string.IsNullOrWhiteSpace(subActionItem))
							{
								resourceItem = new ResourceItem(accessLevel, claims, validForResourceActionItems, actionItem, null);
								Add(resourceItem);
							}
							else
							{
								resourceItem = new ResourceItem(accessLevel, claims, validForResourceActionItems, actionItem, subActionItem);
								Add(resourceItem);
							}
						}
					}
				}
			}
		}

		#endregion

		#endregion
		#region Constructors

		public ResourceItemCollection()
		{
		}

		#endregion
	}
}
